package ar.edu.caece.pl.asin.model.impl;

import ar.edu.caece.pl.alex.model.IToken;
import ar.edu.caece.pl.alex.model.impl.Token;
import ar.edu.caece.pl.asin.manager.IAnalizadorSintactico;
import ar.edu.caece.pl.asin.manager.impl.AbstractAnalizadorSintactico;
import ar.edu.caece.pl.asin.model.ITokenStream;

public class Sentencia1 extends AbstractAnalizadorSintactico implements IAnalizadorSintactico {
	
	/* INICIALIZACION */	
	public Sentencia1 ( ITokenStream ts ) {
		super(ts, false);
	}
	public Sentencia1 ( ITokenStream ts, boolean debugMode ) {
		super(ts,debugMode);
	}

	
	/** 
	 * Devuelve true si reconoce una sentencia de asignacion, 
	 * una expresion dentro de corchetes con asignacion o una expresion entre parentesis
	 */
	public boolean reconocer () {
		
		boolean recognized = true; //(asumimos correctitud hasta demostrar lo contrario)
		
		//----------------------------------------------
		//Agrego info de debug de la produccion
		em.debug( "Reconocer Sentencia1:", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
		//----------------------------------------------
		
		/* <SENTENCIA_1> -> := <EXP> |
                            [ <EXP> ] := <EXP> |
                            ( <FACTOR_2> ) */
		
		
		if ( this.getTokenSiguiente().equals( new Token(IToken.TYPE_ASIGNACION) ) ) {
			
			//<SENTENCIA_1> -> := <EXP>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<SENTENCIA_1> -> := <EXP>", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------
			
			// Reconocer ASIGNACION
			recognized &= this.reconocerToken(IToken.TYPE_ASIGNACION);
			
			// Reconocer Expresion
			IAnalizadorSintactico expresion = new Expresion(this.tokenStream,this.debugMode);
			recognized &= expresion.reconocer();
			
		} else if ( this.getTokenSiguiente().getType() == IToken.TYPE_CORCHETE_IZQ ) {
			
			//<SENTENCIA_1> -> [ <EXP> ] := <EXP>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<SENTENCIA_1> -> [ <EXP> ] := <EXP>", this.getTokenSiguiente() );		//TODO pasarlo a accion semantica
			//----------------------------------------------
			
			// Reconocer CORCHETE_IZQ
			recognized &= this.reconocerToken(IToken.TYPE_CORCHETE_IZQ);
			
			// Reconocer Expresion
			IAnalizadorSintactico expresion = new Expresion(this.tokenStream,this.debugMode);
			recognized &= expresion.reconocer();
			
			// Reconocer CORCHETE_DER
			recognized &= this.reconocerToken(IToken.TYPE_CORCHETE_DER);
			
			// Reconocer ASIGNACION
			recognized &= this.reconocerToken(IToken.TYPE_ASIGNACION);
			
			// Reconocer Expresion
			IAnalizadorSintactico expresion2 = new Expresion(this.tokenStream,this.debugMode);
			recognized &= expresion2.reconocer();
			
		} else if ( this.getTokenSiguiente().equals( new Token(IToken.TYPE_PARENTESIS_IZQ) ) ) {
			
			//<SENTENCIA_1> -> ( <FACTOR_2> )
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<SENTENCIA_1> -> ( <FACTOR_2> )", this.getTokenSiguiente() );	//TODO pasarlo a accion semantica
			//----------------------------------------------
			
			// Reconocer PARENTESIS_IZQ
			recognized &= this.reconocerToken(IToken.TYPE_PARENTESIS_IZQ);
			
			// Reconocer <FACTOR_2>
			IAnalizadorSintactico factor2 = new Factor2(this.tokenStream, this.debugMode);
			recognized &= factor2.reconocer();
			
			// Reconocer PARENTESIS_DER
			recognized &= this.reconocerToken(IToken.TYPE_PARENTESIS_DER);
			
		} else {
			//No deberia darse el caso, pero si se llama a reconocer() en un estado incorrecto deberia salir por aqui
			em.error("Se esperaba " + this.dic.getTokenDescription(IToken.TYPE_ASIGNACION) +
					          " o " + this.dic.getTokenDescription(IToken.TYPE_CORCHETE_IZQ) +
					          " o " + this.dic.getTokenDescription(IToken.TYPE_PARENTESIS_IZQ),
					this.getTokenSiguiente());
			
			recognized = false;
			
			//Tratamiento de errores
			em.recover(this.getClass(), this.tokenStream);
		}
		return recognized;
	}
	
	public static boolean primeros(IToken token) {
		return  token.equals( new Token(IToken.TYPE_ASIGNACION) ) ||
				token.equals( new Token(IToken.TYPE_CORCHETE_IZQ) ) ||
				token.equals( new Token(IToken.TYPE_PARENTESIS_IZQ) );
	}
	
}
